#!/usr/bin/perl -w
use strict;

sub SetCardinal {
   my %a = @_;
   0+(keys %a);
}

sub SetExists {
   defined($_[0]{$_[1]});
}

sub SetString {
   my %a = @_;
   my @b = keys %a;
   return "@b";
}

sub SetUnion {
   my $a = $_[0];
   my $b = $_[1];
   my %u;
   @u{keys %$a, keys %$b} = ();
   return %u;
}

sub SetIntersection {
   my $a = $_[0];
   my $b = $_[1];
   my %i;
   @i{ grep {exists($b->{$_})} keys %$a} = ();
   return %i;
}

sub SetDifference {
   my $a = $_[0];
   my $b = $_[1];
   my %i;
   @i{ grep {!exists($b->{$_})} keys %$a} = ();
   return %i;
}

sub SetSimmetricDifference {
   my $a = $_[0];
   my $b = $_[1];
   my %union = SetUnion($a, $b);
   my %inter = SetIntersection($a, $b);
   my %result = SetDifference(\%union, \%inter);
   return %result;
}

my (%a, %b);
@a{1..4} = ();
@b{2,4,6,8} = ();
print "Hash a = ".SetString(%a)."\n";
print "Hash b = ".SetString(%b)."\n";
print "Cardinal hash a : ".SetCardinal(%a)."\n";
print "Cardinal hash b : ".SetCardinal(%b)."\n";
print "Union a y b : ".SetString(SetUnion(\%a, \%b))."\n";
print "Interseccion a y b : ".SetString(SetIntersection(\%a, \%b))."\n";
print "Diferencia a y b : ".SetString(SetDifference(\%a, \%b))."\n";
print "Diferencia simetrica a y b : ".SetString(SetSimmetricDifference(\%a, \%b))."\n";

